export const createStore = (reducer, enhancer) => {
  if (enhancer){
    return enhancer(createStore)(reducer)
  }
  let currentState = {},
    listeners = []
  function getState(){
    return currentState
  }
  function subscribe(listener){
    listeners.push(listener)
  }
  function dispatch(action){
    currentState = reducer(currentState, action)
    listeners.forEach( v => v() )
  }
  dispatch({
    type:`)(*&^^%$@!@#$%^&**(`
  })
  return {
    getState,
    subscribe,
    dispatch
  }
}

/* export const applyMiddleware = (middleware) => (createStore) => (...args) =>{
  const store = createStore(...args)
  let dispatch = store.dispatch
  const midApi = {
    getState: store.getState,
    dispatch: (...args) => dispatch(...args)
  }
  dispatch = middleware(midApi)(dispatch)
  return {
    ...store,
    dispatch
  }
} */
/* export const applyMiddleware = (...middlewares) => (createStore) => (...args) => {
  const store = createStore(...args)
  let dispatch = store.dispatch
  const midApi = {
    getState: store.getState,
    dispatch: (...args) => dispatch(...args)
  }
  const middlewareChain = middlewares.map(v => v(midApi))
  //经过compose之后变成middleware1(midApi)(middleware2(midApi))
  dispatch = compose(middlewareChain)(dispatch)
  return {
    ...store,
    dispatch
  }
} */
export const applyMiddleware = (...middlewares) => (createStore) => (...args) => {
  //第一层里的store是原始的store，没有任何添加
  //核心任务就是改变返回的dispatch
  //分支任务点就是让dispatch可以实现dispatch = middleware(middleware(dispatch))
  //为了可以实现middleware实现的时候需要多层参数传入，这里接受他的也需要多层调用
  const store = createStore(...args)
  let dispatch = store.dispatch
  const midApi = {
    dispatch: (...args) => dispatch(...args),
    getState: store.getState
  }
  console.log(dispatch)
  //本来是只需要一层middleware，(action)但是使用中可能需要用到原生的Api因此外面多了一层传入thunk = ({dispatch,getState})=>(action),这里进行批量处理
  const middlewareChain = middlewares.map(middleware => middleware(midApi))
  //这里需要一个嵌套函数包装一下middleware，因此在middleware解构的时候也需要多一层的处理，之前两层即可thunk = ({dispatch,getState}) =>next =>(action)
  //这里的next就是嵌套进来的其他函数也就是另一个dispatch
  //当然这里需要一个方法对最外层的函数进行调用，传入的dispatch是最后一层执行的时候调用的
  dispatch = compose(...middlewareChain)(dispatch)
  console.log('72',dispatch)
  return {
    ...store,
    dispatch
  }
}
//compose(fn1,fn2,fn3) >>> fn1(fn2(fn3))其中fn1的next就是fn2, fn1(fn2(fn3))为一个未执行的函数体，需要()调用一次
/* export const compose = (fns)  => {
  debugger;
  //return funs.reduce((ret, item) => (...args) => ret(item(...args)))
  //因为是两层嵌套函数因此这里不能直接返回一个函数，需要在进行一次包装，也就是可以传入一个dispatch
  return fns.reduce(function(ret, item){
    return function(...args){
      return ret(item(...args))
    }
  })
} */
export const compose = (...fns)  => {
  return fns.reduce((ret, item) => (...args) => {
    return ret(item(...args))
  })
}
function boundDispatch(creator, dispatch){
  return (...args) => {
    dispatch(creator(...args))
  }
}

export const bindActionCreator = (creators, dispatch) => {
  return Object.keys(creators).reduce( (ret, item) => {
    ret[item] = boundDispatch(creators[item], dispatch)
    return ret
  }, {} )
}